package com.xialuo.study.tools;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Component
public class ChartGenerator {
    private static final Logger logger = LoggerFactory.getLogger(ChartGenerator.class);

    @Tool(description = "从CSV格式数据生成图表。支持折线图(line)和条形图(bar)。")
    public String generateChart(
        @ToolParam(description = "要生成的图表类型：line 或 bar") String chartType,
        @ToolParam(description = "X轴的字段名称") String xAxis,
        @ToolParam(description = "Y轴的字段名称") String yAxis,
        @ToolParam(description = "CSV格式的数据，需要包含表头，用换行符分隔行，用逗号分隔列，示例：\n" +
            "month,sales\n" +
            "1月,100\n" +
            "2月,150\n" +
            "3月,200\n") String csvData
    ) {
        try {
            logger.info("开始生成图表，类型: {}, X轴: {}, Y轴: {}", chartType, xAxis, yAxis);

            // 解析CSV数据
            List<Map<String, Object>> dataList = parseCSVData(csvData);
            if (dataList.isEmpty()) {
                throw new IllegalArgumentException("数据为空或格式不正确");
            }

            // 验证数据
            validateData(dataList, xAxis, yAxis);

            // 创建并保存图表
            JFreeChart chart = createChart(chartType, xAxis, yAxis, dataList);
            String fileName = "chart_" + System.currentTimeMillis() + ".png";
            saveChart(chart, fileName);

            logger.info("图表生成成功: {}", fileName);
            return "图表已成功生成: " + fileName;
        } catch (Exception e) {
            logger.error("生成图表失败: {}", e.getMessage(), e);
            throw new RuntimeException("生成图表失败: " + e.getMessage());
        }
    }

    /**
     * 解析CSV格式数据
     */
    private List<Map<String, Object>> parseCSVData(String csvData) throws IOException {
        if (csvData == null || csvData.trim().isEmpty()) {
            throw new IllegalArgumentException("CSV数据不能为空");
        }

        List<Map<String, Object>> result = new ArrayList<>();

        try (CSVParser parser = CSVParser.parse(csvData, CSVFormat.DEFAULT.withFirstRecordAsHeader())) {
            for (CSVRecord record : parser) {
                Map<String, Object> row = new LinkedHashMap<>();
                parser.getHeaderNames().forEach(header ->
                    row.put(header, parseValue(record.get(header)))
                );
                result.add(row);
            }
        }

        return result;
    }

    /**
     * 尝试将字符串值转换为数值
     */
    private Object parseValue(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }

        try {
            // 尝试解析为数字
            if (value.contains(".")) {
                return Double.parseDouble(value);
            } else {
                return Long.parseLong(value);
            }
        } catch (NumberFormatException e) {
            // 如果不是数字，保持字符串格式
            return value;
        }
    }

    /**
     * 验证数据
     */
    private void validateData(List<Map<String, Object>> dataList, String xAxis, String yAxis) {
        // 验证字段存在
        if (!dataList.get(0).containsKey(xAxis)) {
            throw new IllegalArgumentException("数据中不存在X轴字段: " + xAxis);
        }
        if (!dataList.get(0).containsKey(yAxis)) {
            throw new IllegalArgumentException("数据中不存在Y轴字段: " + yAxis);
        }

        // 验证Y轴数据类型
        boolean hasValidYValue = false;
        for (Map<String, Object> row : dataList) {
            Object yValue = row.get(yAxis);
            if (yValue != null) {
                try {
                    parseNumber(yValue);
                    hasValidYValue = true;
                    break;
                } catch (Exception ignored) {
                }
            }
        }

        if (!hasValidYValue) {
            throw new IllegalArgumentException("Y轴字段不包含有效的数值数据: " + yAxis);
        }
    }

    private JFreeChart createChart(String chartType, String xAxis, String yAxis, List<Map<String, Object>> dataList) {
        switch (chartType.toLowerCase()) {
            case "line":
                return createLineChart(xAxis, yAxis, dataList);
            case "bar":
                return createBarChart(xAxis, yAxis, dataList);
            default:
                throw new IllegalArgumentException("不支持的图表类型: " + chartType);
        }
    }

    private JFreeChart createLineChart(String xAxis, String yAxis, List<Map<String, Object>> dataList) {
        // 检查X轴是否是数值类型
        boolean isXNumeric = isNumericField(dataList, xAxis);

        if (isXNumeric) {
            // 如果X轴是数值型，使用XYLineChart
            return createNumericXLineChart(xAxis, yAxis, dataList);
        } else {
            // 如果X轴不是数值型，使用CategoryDataset
            return createCategoryLineChart(xAxis, yAxis, dataList);
        }
    }

    private JFreeChart createNumericXLineChart(String xAxis, String yAxis, List<Map<String, Object>> dataList) {
        XYSeries series = new XYSeries(yAxis);

        for (Map<String, Object> data : dataList) {
            try {
                Object xValue = data.get(xAxis);
                Object yValue = data.get(yAxis);

                if (xValue != null && yValue != null) {
                    double x = parseNumber(xValue);
                    double y = parseNumber(yValue);
                    series.add(x, y);
                }
            } catch (Exception e) {
                logger.warn("跳过无效数据点: x={}, y={}", data.get(xAxis), data.get(yAxis));
            }
        }

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series);

        return ChartFactory.createXYLineChart(
            yAxis + " vs " + xAxis,
            xAxis,
            yAxis,
            dataset
        );
    }

    private JFreeChart createCategoryLineChart(String xAxis, String yAxis, List<Map<String, Object>> dataList) {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        for (Map<String, Object> data : dataList) {
            try {
                Object xValue = data.get(xAxis);
                Object yValue = data.get(yAxis);

                if (xValue != null && yValue != null) {
                    String x = xValue.toString();
                    double y = parseNumber(yValue);
                    dataset.addValue(y, yAxis, x);
                }
            } catch (Exception e) {
                logger.warn("跳过无效数据点: x={}, y={}", data.get(xAxis), data.get(yAxis));
            }
        }

        return ChartFactory.createLineChart(
            yAxis + " vs " + xAxis,
            xAxis,
            yAxis,
            dataset,
            PlotOrientation.VERTICAL,
            true,
            true,
            false
        );
    }

    private JFreeChart createBarChart(String xAxis, String yAxis, List<Map<String, Object>> dataList) {
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        for (Map<String, Object> data : dataList) {
            try {
                Object xValue = data.get(xAxis);
                Object yValue = data.get(yAxis);

                if (xValue != null && yValue != null) {
                    String category = xValue.toString();
                    double value = parseNumber(yValue);
                    dataset.addValue(value, yAxis, category);
                }
            } catch (Exception e) {
                logger.warn("跳过无效数据点: x={}, y={}", data.get(xAxis), data.get(yAxis));
            }
        }

        return ChartFactory.createBarChart(
            yAxis + " by " + xAxis,
            xAxis,
            yAxis,
            dataset
        );
    }

    private boolean isNumericField(List<Map<String, Object>> dataList, String fieldName) {
        if (dataList.isEmpty()) {
            return false;
        }

        // 检查前5条记录（或全部记录如果少于5条）
        int samplesToCheck = Math.min(5, dataList.size());
        int numericCount = 0;

        for (int i = 0; i < samplesToCheck; i++) {
            try {
                Object value = dataList.get(i).get(fieldName);
                if (value != null) {
                    parseNumber(value); // 尝试解析为数字
                    numericCount++;
                }
            } catch (Exception ignored) {
                // 非数值类型
            }
        }

        // 如果超过一半的样本是数值型，认为是数值列
        return numericCount > samplesToCheck / 2;
    }

    private double parseNumber(Object value) {
        if (value instanceof Number) {
            return ((Number) value).doubleValue();
        } else if (value instanceof String) {
            String str = ((String) value).trim();
            try {
                return Double.parseDouble(str);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("无法将值 '" + str + "' 转换为数值");
            }
        } else {
            throw new IllegalArgumentException("无法将类型 " + value.getClass().getName() + " 转换为数值");
        }
    }

    private void saveChart(JFreeChart chart, String fileName) throws IOException {
        ChartUtils.saveChartAsPNG(
            new File(fileName),
            chart,
            800,
            600
        );
    }
}
